#include "common_param.h"
// std
#include "stdlib.h"
#include "string.h"
// lib
#include "debug.h"
#include "crcLib.h"
// bsp
// #include "bsp_network.h"
#include "bsp_store.h"
// app
#include "flash_divide.h"

// 通用固定协议定义
#define PROJECT_NAME_LEN                    32                                      // 项目名长度
#define PROJECT_NAME_OFFSET                 0x200                                   // 项目名于首地址的偏移量-注意位置！平台默认一包512字节
#define PROJECT_VERSION_LEN                 16                                      // 版本号长度
#define PROJECT_VERSION_OFFSET              0x300                                   // 版本号于首地址的偏移量

static const uint8_t project_name[PROJECT_NAME_LEN]       __attribute__ ((at(APPLICATION_MAIN_ADDR_START + PROJECT_NAME_OFFSET)))    = PROJECT_NAME;
static const uint8_t project_version[PROJECT_VERSION_LEN] __attribute__ ((at(APPLICATION_MAIN_ADDR_START + PROJECT_VERSION_OFFSET))) = SOFTWARE_VERSION;

// 运行参数
parameter_t system_param;

//从掉电储存管理更新参数
void Common_Param_Update_Form_Rom(void)
{
    //从掉电储存器读取储存参数表，并更新到运行参数表中
    Common_Param_Read_From_Rom();
    //检查参数合法性
    // Param_Check();
}

//将参数表写入到掉电储存器件
uint8_t Common_Param_Save_To_Rom(void)
{
    //将参数写入内部 FLASH
    #if PARAM_USE_INS_FLASH
        //写入固件升级参数
        Store_Ins_Flash_Write((uint32_t)(PARAMETER_ADDR_START+up_version_offset), (uint8_t *)(&system_param.device_param.update_version), sizeof(uint8_t));
        Store_Ins_Flash_Write((uint32_t)(PARAMETER_ADDR_START+up_package_offset), (uint8_t *)(&system_param.device_param.update_package), sizeof(uint8_t));
        Store_Ins_Flash_Write((uint32_t)(PARAMETER_ADDR_START+up_try_times_offset), (uint8_t *)(&system_param.device_param.update_try_times), sizeof(uint8_t));
        // //写入杀虫等定时参数
        // Store_Ins_Flash_Write((uint32_t)(PARAMETER_ADDR_START+dis_control_mode), (uint16_t *)(&system_param.dis_param.control_mode), sizeof(uint16_t));
        // Store_Ins_Flash_Write((uint32_t)(PARAMETER_ADDR_START+dis_run_time), (uint16_t *)(&system_param.dis_param.run_time), sizeof(uint16_t));
        // Store_Ins_Flash_Write((uint32_t)(PARAMETER_ADDR_START+dis_end_time), (uint16_t *)(&system_param.dis_param.end_time), sizeof(uint16_t));
    #endif
    _DEBUG_PRINT(DBG_API, "save param to rom\r\n");
    return 1;
}

//从掉电储存器件读取参数表
uint8_t Common_Param_Read_From_Rom(void)
{
    //从内部 FLASH 读取参数
    #if PARAM_USE_INS_FLASH
        //固件升级参数
        Store_Ins_Flash_Read((uint32_t)(PARAMETER_ADDR_START+up_version_offset), (uint8_t *)(&system_param.device_param.update_version), sizeof(uint8_t));
        Store_Ins_Flash_Read((uint32_t)(PARAMETER_ADDR_START+up_package_offset), (uint8_t *)(&system_param.device_param.update_package), sizeof(uint8_t));
        Store_Ins_Flash_Read((uint32_t)(PARAMETER_ADDR_START+up_try_times_offset), (uint8_t *)(&system_param.device_param.update_try_times), sizeof(uint8_t));
        // //读取杀虫等定时参数
        // Store_Ins_Flash_Read((uint32_t)(PARAMETER_ADDR_START+dis_control_mode), (uint16_t *)(&system_param.dis_param.control_mode), sizeof(uint16_t));
        // Store_Ins_Flash_Read((uint32_t)(PARAMETER_ADDR_START+dis_run_time), (uint16_t *)(&system_param.dis_param.run_time), sizeof(uint16_t));
        // Store_Ins_Flash_Read((uint32_t)(PARAMETER_ADDR_START+dis_end_time), (uint16_t *)(&system_param.dis_param.end_time), sizeof(uint16_t));
    #endif
    _DEBUG_PRINT(DBG_API, "load param from rom\r\n");
    return 1;
}

// 更新服务器IP端口到运行参数表
void Common_Param_Setting_Server_Ipv4(uint8_t *ip, uint8_t *port)
{
    memset(&system_param.server_param, 0x00, sizeof(server_parameter_t));
    memcpy(system_param.server_param.server_ipv4, ip, strlen((char *)ip));
    memcpy(system_param.server_param.server_port, port, strlen((char *)port));
}

// 从设备更新参数
void Common_Param_Update_Form_Device(void)
{
    // 获取设备ID
    Hoire_Id_Generate_Hash(system_param.device_param.device_id);
    // 获取版本号
    Hoire_Get_Firmware_Version();
    // 获取SIM卡iccid
    // Network_Cellular_Get_Iccid(system_param.device_param.sim_iccid);
    system_param.device_param.sim_iccid[20] = '\0';
    _DEBUG_PRINT(DBG_API, "get param from devices\r\n");
}

// 从固定地址读取固件名、boot版本号、app版本号
void Hoire_Get_Firmware_Version(void)
{
    memcpy(system_param.device_param.firmware_name,     (uint32_t *)(APPLICATION_MAIN_ADDR_START + PROJECT_NAME_OFFSET),    PROJECT_NAME_LEN);
    memcpy(system_param.device_param.firmware_boot_ver, (uint32_t *)(BOOTLOADER_ADDR_START       + PROJECT_VERSION_OFFSET), PROJECT_VERSION_LEN);
    memcpy(system_param.device_param.firmware_app_ver,  (uint32_t *)(APPLICATION_MAIN_ADDR_START + PROJECT_VERSION_OFFSET), PROJECT_VERSION_LEN);
}

/**
 * @brief 生成48bit海睿ID
 * 
 * @param id_string 传入默认16byte数组
 */
void Hoire_Id_Generate_Hash(uint8_t *id_string)
{
    //读取96bit芯片唯一ID unique device ID
    uint32_t x = *(uint32_t*)(0x1FFF7590);
    uint32_t y = *(uint32_t*)(0x1FFF7594);
    uint32_t z = *(uint32_t*)(0x1FFF7598);
    //FNV-1a哈希算法，生成48bit海睿ID
    const uint32_t FNV_prime = 16777619;
    uint32_t hash1 = 2166136261;
    uint32_t hash2 = 2166136261;
    hash1 = (hash1 ^ x) * FNV_prime;
    hash2 = (hash2 ^ (x >> 16)) * FNV_prime;
    hash1 = (hash1 ^ y) * FNV_prime;
    hash2 = (hash2 ^ (y >> 16)) * FNV_prime;
    hash1 = (hash1 ^ z) * FNV_prime;
    hash2 = (hash2 ^ (z >> 16)) * FNV_prime;
    hash1 &= 0x00FFFFFF;//取hash1低24位数据
    hash2 &= 0x00FFFFFF;//取hash2低24位数据
    //拼接成48bit数据，并转换成字符串保存到参数
    sprintf((char *)id_string, "%X%X", hash2, hash1);
}

// 检查字符串是否为合法的IPV4地址
uint8_t Common_Param_Is_Ipv4(uint8_t *ip)
{
    if (ip == NULL || ip[0] == '0' || ip[0] == '\0')
        return 0;
    for (int i = 0, count = 0; i < strlen((char *)ip); i++)
    {
        if ((ip[i] != '.') && (ip[i] < '0' || ip[i] > '9'))
            return 0;
        if (ip[i] == '.')
        {
            count++;
            if (count > 3)
                return 0;
        }
    }
    int ip_num[4] = {-1, -1, -1, -1};
    uint8_t ip_s[4][4];
    memset(ip_s, 0, sizeof(uint8_t[4]) * 4);
    sscanf((char *)ip, "%[^.].%[^.].%[^.].%[^ ]", ip_s[0], ip_s[1], ip_s[2], ip_s[3]);
    sscanf((char *)ip_s[0], "%d", &ip_num[0]);
    sscanf((char *)ip_s[1], "%d", &ip_num[1]);
    sscanf((char *)ip_s[2], "%d", &ip_num[2]);
    sscanf((char *)ip_s[3], "%d", &ip_num[3]);
    for (int i = 0; i < 4; i++)
        if (strlen((char *)ip_s[i]) == 0 || (ip_s[i][0] == '0' && ip_s[i][1] != '\0') || ip_num[i] < 0 || ip_num[i] > 255)
            return 0;
    return 1;
}

// 生成随机UUID
// 参数必须为长度至少37的数组
void Common_Param_Random_Uuid(uint8_t *buf)
{
    const char *c = "89ab";
    char *p = (char *)buf;
    int n;
    for (n = 0; n < 16; ++n)
    {
        int b = rand() % 255;
        switch (n)
        {
        case 6:
            sprintf(p, "4%x", b % 15);
            break;
        case 8:
            sprintf(p, "%c%x", c[rand() % strlen(c)], b % 15);
            break;
        default:
            sprintf(p, "%02x", b);
            break;
        }
        p += 2;
        switch (n)
        {
        case 3:
        case 5:
        case 7:
        case 9:
            *p++ = '-';
            break;
        }
    }
}
